package dawn.jxufe.community.service;

import dawn.jxufe.community.entity.User;
import dawn.jxufe.community.util.CommunityConstant;
import dawn.jxufe.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author dawn21
 * @version 1.0
 * @date 2022/8/11 9:26
 * @component
 */
@Service
public class FollowService implements CommunityConstant {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    // 关注功能方法。存关注目标、存粉丝。两个事务，需要事务管理。
    public void follow(int userId, int entityType, int entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followee = RedisKeyUtil.getFolloweeKey(userId, entityType); // 目标
                String follower = RedisKeyUtil.getFollowerKey(entityType, entityId); // 粉丝

                operations.multi(); // 开启事务。

                // 存数据。
                operations.opsForZSet().add(followee, entityId, System.currentTimeMillis());
                operations.opsForZSet().add(follower, userId, System.currentTimeMillis());

                return operations.exec(); // 执行事务。
            }
        });
    }

    // 取消关注功能方法。取消关注目标、取消粉丝。两个事务，需要事务管理。
    public void unfollow(int userId, int entityType, int entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followee = RedisKeyUtil.getFolloweeKey(userId, entityType); // 目标
                String follower = RedisKeyUtil.getFollowerKey(entityType, entityId); // 粉丝

                operations.multi(); // 开启事务。

                // 移除数据。
                operations.opsForZSet().remove(followee, entityId);
                operations.opsForZSet().remove(follower, userId);

                return operations.exec(); // 执行事务。
            }
        });
    }

    // 查询用户关注了多少实体。
    public long findFolloweeCount(int userId, int entityType) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().zCard(followeeKey);
    }

    // 查询实体的粉丝数量。
    public long findFollowerCount(int entityType, int entityId) {
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }

    // 查询判断当前用户有没有关注那个目标。
    public boolean hasFollowed(int userId, int entityType, int entityId) {
        // 查询当前用户的关注的目标系列中有没有这个实体。
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
    }

    // 查询某个用户关注的人。
    public List<Map<String, Object>> findFollowees(int userId, int offset, int limit) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);

        if (targetIds == null) {
            return null;
        }

        List<Map<String, Object>> list = new ArrayList<>();
        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User user = userService.findUserById(targetId);
            map.put("user", user);
            // 获取关注的时间。存的时候是毫秒数。
            Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);
            map.put("followTime", new Date(score.longValue()));
            list.add(map);
        }

        return list;

    }

    // 查询某个用户的粉丝。
    public List<Map<String, Object>> findFollowers(int userId, int offset, int limit) {
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);

        if (targetIds == null) {
            return null;
        }

        List<Map<String, Object>> list = new ArrayList<>();
        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User user = userService.findUserById(targetId);
            map.put("user", user);
            // 获取关注的时间。存的时候是毫秒数。
            Double score = redisTemplate.opsForZSet().score(followerKey, targetId);
            map.put("followTime", new Date(score.longValue()));
            list.add(map);
        }

        return list;

    }

}
